home *** CD-ROM | disk | FTP | other *** search
- /* bind.c */
-
- #include "bindings.h"
- #include "mush.h"
-
- extern char *c_macro();
- static un_bind();
-
- struct cmd_map *cmd_map, *line_map, *bang_map;
-
- /*
- * Bindings are added here in REVERSE of the order that
- * they will be displayed! Display order is based on a
- * guess about the frequency of use and (to a lesser
- * extent) how hard they are to remember.
- *
- * The user's own new bindings, if any, will be displayed
- * before any of these default bindings.
- */
- init_bindings()
- {
- #ifdef CURSES
- /* Help gets displayed last */
- add_bind("?", C_HELP, NULL, &cmd_map);
- add_bind("V", C_VERSION, NULL, &cmd_map);
-
- /* Miscellaneous shell commands */
- add_bind("%", C_CHDIR, NULL, &cmd_map);
- add_bind("|", C_PRINT_MSG, NULL, &cmd_map);
- add_bind("!", C_SHELL_ESC, NULL, &cmd_map);
- add_bind(":", C_CURSES_ESC, NULL, &cmd_map);
-
- /* Mush customization commands */
- /* NOTE: No default C_MACRO bindings */
- add_bind(")", C_SAVEOPTS, NULL, &cmd_map);
- add_bind("(", C_SOURCE, NULL, &cmd_map);
- add_bind("&!", C_MAP_BANG, NULL, &cmd_map);
- add_bind("&:", C_MAP, NULL, &cmd_map);
- add_bind("&&", C_BIND_MACRO, NULL, &cmd_map);
- add_bind("v", C_VAR_SET, NULL, &cmd_map);
- add_bind("i", C_IGNORE, NULL, &cmd_map);
- add_bind("h", C_OWN_HDR, NULL, &cmd_map);
- add_bind("B", C_UNBIND, NULL, &cmd_map);
- add_bind("b", C_BIND, NULL, &cmd_map);
- add_bind("a", C_ALIAS, NULL, &cmd_map);
-
- /* Display modification commands */
- add_bind("\022", C_REVERSE, NULL, &cmd_map); /* ^R */
- add_bind("\014", C_REDRAW, NULL, &cmd_map); /* ^L */
- add_bind("Z", C_PREV_SCREEN, NULL, &cmd_map);
- add_bind("z", C_NEXT_SCREEN, NULL, &cmd_map);
-
- /* Searching and sorting commands */
- add_bind("\016", C_CONT_SEARCH, NULL, &cmd_map); /* ^N */
- add_bind("\037", C_PREV_SEARCH, NULL, &cmd_map); /* ^/ */
- add_bind("/", C_NEXT_SEARCH, NULL, &cmd_map);
- add_bind("O", C_REV_SORT, NULL, &cmd_map);
- add_bind("o", C_SORT, NULL, &cmd_map);
-
- /* Ways to get out */
- add_bind("X", C_EXIT_HARD, NULL, &cmd_map);
- add_bind("x", C_EXIT, NULL, &cmd_map);
- add_bind("Q", C_QUIT_HARD, NULL, &cmd_map);
- add_bind("q", C_QUIT, NULL, &cmd_map);
-
- /* Folder modification commands */
- add_bind("\025", C_UPDATE, NULL, &cmd_map); /* ^U */
- add_bind("\020", C_PRESERVE, NULL, &cmd_map); /* ^P */
- add_bind("W", C_WRITE_LIST, NULL, &cmd_map);
- add_bind("w", C_WRITE_MSG, NULL, &cmd_map);
- add_bind("U", C_UNDEL_LIST, NULL, &cmd_map);
- add_bind("u", C_UNDEL_MSG, NULL, &cmd_map);
- add_bind("S", C_SAVE_LIST, NULL, &cmd_map);
- add_bind("s", C_SAVE_MSG, NULL, &cmd_map);
- add_bind("f", C_FOLDER, NULL, &cmd_map);
- add_bind("D", C_DELETE_LIST, NULL, &cmd_map);
- add_bind("d", C_DELETE_MSG, NULL, &cmd_map);
- add_bind("C", C_COPY_LIST, NULL, &cmd_map);
- add_bind("c", C_COPY_MSG, NULL, &cmd_map);
-
- /* Cursor movement and message selection */
- add_bind("g", C_GOTO_MSG, NULL, &cmd_map);
- add_bind("}", C_BOTTOM_PAGE, NULL, &cmd_map);
- add_bind("{", C_TOP_PAGE, NULL, &cmd_map);
- add_bind("$", C_LAST_MSG, NULL, &cmd_map);
- add_bind("^", C_FIRST_MSG, NULL, &cmd_map);
- add_bind("\013",C_PREV_MSG, NULL, &cmd_map); /* ^K */
- add_bind("\012", C_NEXT_MSG, NULL, &cmd_map); /* ^J */
- add_bind("-",C_PREV_MSG, NULL, &cmd_map);
- add_bind("+",C_NEXT_MSG, NULL, &cmd_map);
- add_bind("K", C_PREV_MSG, NULL, &cmd_map);
- add_bind("k", C_PREV_MSG, NULL, &cmd_map);
- add_bind("J", C_NEXT_MSG, NULL, &cmd_map);
- add_bind("j", C_NEXT_MSG, NULL, &cmd_map);
-
- /* Mail-sending commands */
- add_bind("R", C_REPLY_ALL, NULL, &cmd_map);
- add_bind("r", C_REPLY_SENDER, NULL, &cmd_map);
- add_bind("M", C_MAIL_FLAGS, NULL, &cmd_map);
- add_bind("m", C_MAIL, NULL, &cmd_map);
-
- /* Mail-reading commands */
- add_bind(".", C_DISPLAY_MSG, NULL, &cmd_map);
- add_bind("T", C_TOP_MSG, NULL, &cmd_map);
- add_bind("t", C_DISPLAY_MSG, NULL, &cmd_map);
- add_bind("p", C_DISPLAY_MSG, NULL, &cmd_map);
- add_bind("n", C_DISPLAY_NEXT, NULL, &cmd_map);
-
- #endif /* CURSES */
- }
-
- /* Bindable function names.
- * Most of these can't be used if CURSES is not defined,
- * but help and lookups get confused if they aren't all here.
- */
- struct cmd_map map_func_names[] = {
- /* These MUST be in numerical order; see bindings.h */
- { C_NULL, "no-op", NULL, NULL_MAP },
- { C_GOTO_MSG, "goto-msg", NULL, NULL_MAP },
- { C_WRITE_LIST, "write-list", NULL, NULL_MAP },
- { C_WRITE_MSG, "write", NULL, NULL_MAP },
- { C_SAVE_LIST, "save-list", NULL, NULL_MAP },
- { C_SAVE_MSG, "save", NULL, NULL_MAP },
- { C_COPY_LIST, "copy-list", NULL, NULL_MAP },
- { C_COPY_MSG, "copy", NULL, NULL_MAP },
- { C_DELETE_LIST, "delete-list", NULL, NULL_MAP },
- { C_DELETE_MSG, "delete", NULL, NULL_MAP },
- { C_UNDEL_LIST, "undelete-list", NULL, NULL_MAP },
- { C_UNDEL_MSG, "undelete", NULL, NULL_MAP },
- { C_REDRAW, "redraw", NULL, NULL_MAP },
- { C_REVERSE, "reverse-video", NULL, NULL_MAP },
- { C_NEXT_MSG, "next-msg", NULL, NULL_MAP },
- { C_PREV_MSG, "back-msg", NULL, NULL_MAP },
- { C_FIRST_MSG, "first-msg", NULL, NULL_MAP },
- { C_LAST_MSG, "last-msg", NULL, NULL_MAP },
- { C_TOP_PAGE, "top-page", NULL, NULL_MAP },
- { C_BOTTOM_PAGE, "bottom-page", NULL, NULL_MAP },
- { C_NEXT_SCREEN, "screen-next", NULL, NULL_MAP },
- { C_PREV_SCREEN, "screen-back", NULL, NULL_MAP },
- { C_SOURCE, "source", NULL, NULL_MAP },
- { C_SAVEOPTS, "saveopts", NULL, NULL_MAP },
- { C_NEXT_SEARCH, "search-next", NULL, NULL_MAP },
- { C_PREV_SEARCH, "search-back", NULL, NULL_MAP },
- { C_CONT_SEARCH, "search-again", NULL, NULL_MAP },
- { C_PRESERVE, "preserve", NULL, NULL_MAP },
- { C_REV_SORT, "sort-reverse", NULL, NULL_MAP },
- { C_SORT, "sort", NULL, NULL_MAP },
- { C_QUIT_HARD, "quit!", NULL, NULL_MAP },
- { C_QUIT, "quit", NULL, NULL_MAP },
- { C_EXIT_HARD, "exit!", NULL, NULL_MAP },
- { C_EXIT, "exit", NULL, NULL_MAP },
- { C_UPDATE, "update", NULL, NULL_MAP },
- { C_FOLDER, "folder", NULL, NULL_MAP },
- { C_SHELL_ESC, "shell-escape", NULL, NULL_MAP },
- { C_CURSES_ESC, "line-mode", NULL, NULL_MAP },
- { C_PRINT_MSG, "lpr", NULL, NULL_MAP },
- { C_CHDIR, "chdir", NULL, NULL_MAP },
- { C_VAR_SET, "variable", NULL, NULL_MAP },
- { C_IGNORE, "ignore", NULL, NULL_MAP },
- { C_ALIAS, "alias", NULL, NULL_MAP },
- { C_OWN_HDR, "my-hdrs", NULL, NULL_MAP },
- { C_VERSION, "version", NULL, NULL_MAP },
- { C_MAIL_FLAGS, "mail-flags", NULL, NULL_MAP },
- { C_MAIL, "mail", NULL, NULL_MAP },
- { C_REPLY_ALL, "reply-all", NULL, NULL_MAP },
- { C_REPLY_SENDER, "reply", NULL, NULL_MAP },
- { C_DISPLAY_NEXT, "display-next", NULL, NULL_MAP },
- { C_DISPLAY_MSG, "display", NULL, NULL_MAP },
- { C_TOP_MSG, "top", NULL, NULL_MAP },
- { C_BIND_MACRO, "bind-macro", NULL, NULL_MAP },
- { C_BIND, "bind", NULL, NULL_MAP },
- { C_UNBIND, "unbind", NULL, NULL_MAP },
- { C_MAP_BANG, "map!", NULL, NULL_MAP },
- { C_MAP, "map", NULL, NULL_MAP },
- { C_MACRO, "macro", NULL, NULL_MAP },
- /* C_HELP Must be the last one! */
- { C_HELP, "help", NULL, NULL_MAP }
- };
-
- #ifdef CURSES
-
- /*
- * getcmd() is called from curses mode only. It waits for char input from
- * the user via m_getchar() (which means that a macro could provide input)
- * and then compares the chars input against the "bind"ings set up by the
- * user (or the defaults). For example, 'j' could bind to "next msg" which
- * is interpreted by the big switch statement in curses_command() (curses.c).
- * getcmd() returns the int-value of the curses command the input is "bound"
- * to. If the input is unrecognized, C_NULL is returned (curses_command()
- * might require some cleanup, so this is valid, too).
- *
- * Since the input could originate from a macro rather than the terminal,
- * check to see if this is the case and search for a '[' char which indicates
- * that there is a curses command or other "long" command to be executed.
- */
- getcmd()
- {
- char buf[MAX_BIND_LEN * 3];
- register int c, m, match;
- register char *p = buf;
- register struct cmd_map *list;
-
- bzero(buf, MAX_BIND_LEN);
- active_cmd = NULL_MAP;
- c = m_getchar();
- /* If user did job control (^Z), then the interrupt flag will be
- * set. Be sure it's unset before continuing.
- */
- turnoff(glob_flags, WAS_INTR);
- if (isdigit(c)) {
- buf[0] = c;
- buf[1] = '\0';
- Ungetstr(buf); /* So mac_flush can clear on error */
- return C_GOTO_MSG;
- }
- for (;;) {
- if (ison(glob_flags, IN_MACRO) && c == MAC_LONG_CMD)
- return long_mac_cmd(c, TRUE);
- else
- *p++ = c;
- m = 0;
- for (list = cmd_map; list; list = list->m_next) {
- if ((match = prefix(buf, list->m_str)) == MATCH) {
- if (debug)
- print("\"%s\" ",
- ctrl_strcpy(buf,
- map_func_names[list->m_cmd].m_str,
- TRUE));
- if (list->m_cmd == C_MACRO) {
- curs_macro(list->x_str);
- return getcmd();
- }
- active_cmd = list;
- return (int)list->m_cmd;
- } else if (match != NO_MATCH)
- m++;
- }
- if (m == 0) {
- if (debug) {
- char tmp[sizeof buf];
- print("No binding for \"%s\" found.",
- ctrl_strcpy(tmp, buf, TRUE));
- }
- return C_NULL;
- }
- c = m_getchar();
- }
- }
-
- #endif /* CURSES */
-
- /*
- * bind_it() is used to set or unset bind, map and map! settings.
- * bind is used to accelerate curses commands by mapping key sequences
- * to curses commands. map is used to accelerate command mode keysequences
- * by simulating stdin. map! is the same, but used when in compose mode.
- *
- * bind_it() doesn't touch messages; return -1 for curses mode.
- * return -2 to have curses command set CNTD_CMD to prevent screen refresh
- * to allow user to read output in case of multiple lines.
- *
- * Since this routine deals with a lot of binding and unbinding of things
- * like line-mode "map"s and is interactive (calls Getstr()), be very careful
- * not to allow expansions during interaction.
- */
- bind_it(len, argv)
- char **argv;
- {
- char string[MAX_BIND_LEN], buf[256], *name = NULL;
- char *rawstr; /* raw format of string (ptr to string if no argv avail) */
- char ascii[MAX_BIND_LEN*2]; /* printable ascii version of string */
- register int x;
- SIGRET (*oldint)(), (*oldquit)();
- struct cmd_map **map_list;
- int unbind = (argv && **argv == 'u');
- int map = 0, is_bind_macro = 0;
- int ret = 0 - iscurses; /* return value */
-
- if (argv && !strcmp(name = *argv, "bind-macro"))
- is_bind_macro++;
-
- if (map = (argv && (!strcmp(name, "map!") || !strcmp(name, "unmap!"))))
- map_list = &bang_map;
- else if (map = (argv && (!strcmp(name, "map") || !strcmp(name, "unmap"))))
- map_list = &line_map;
- else
- map_list = &cmd_map;
-
- if (argv && *++argv && !strcmp(*argv, "-?"))
- /* Subtract ret and iscurses to signal output */
- return help(0, unbind? name+2 : name, cmd_help) - ret - iscurses;
-
- if (iscurses)
- on_intr();
-
- if (unbind) {
- if (!*argv) {
- char savec = complete;
- complete = 0;
- print("%s what? ", name);
- len = Getstr(buf, sizeof buf, 0);
- complete = savec;
- if (len <= 0) {
- if (iscurses)
- off_intr();
- return -1;
- }
- rawstr = m_xlate(buf);
- } else
- rawstr = m_xlate(*argv);
- if (!un_bind(rawstr, map_list)) {
- (void) ctrl_strcpy(ascii, rawstr, TRUE);
- print("\"%s\" isn't bound to a command.\n", ascii);
- }
- if (iscurses)
- off_intr();
- return ret;
- }
- if (argv && *argv) {
- rawstr = m_xlate(*argv);
- (void) ctrl_strcpy(ascii, rawstr, TRUE);
- if (!*++argv) {
- /*
- * determine whether "argv" references a "map" or a "bind"
- */
- int binding = c_bind(rawstr, *map_list);
- if (binding == C_MACRO) {
- char *mapping = c_macro(NULL, rawstr, *map_list);
- if (mapping) {
- print("\"%s\" is mapped to ", ascii);
- print_more("\"%s\".\n",
- ctrl_strcpy(buf, mapping, FALSE));
- } else
- print("\"%s\" isn't mapped.\n", ascii);
- } else if (binding)
- print("\"%s\" is %s to \"%s\".\n", ascii,
- map? "mapped" : "bound", map_func_names[binding].m_str);
- else if (map)
- print("\"%s\" isn't mapped.\n", ascii);
- else
- print("\"%s\" isn't bound to a command.\n", ascii);
- if (iscurses)
- off_intr();
- return ret;
- }
- } else {
- char savec = complete;
- complete = 0;
- print("%s [<CR>=all, -?=help]: ", name);
- len = Getstr(string, MAX_BIND_LEN-1, 0);
- complete = savec;
- if (len == 0) {
- int add_to_ret = iscurses;
- #ifdef CURSES
- if (iscurses)
- move(LINES-1, 0), refresh();
- #endif
- if (map || is_bind_macro)
- add_to_ret = !c_macro(name, NULL, *map_list);
- else
- add_to_ret = !c_bind(NULL, *map_list);
- if (iscurses)
- off_intr();
- /* signal CTND_CMD if there was output */
- return ret - add_to_ret;
- }
- if (len < 0) {
- if (iscurses)
- off_intr();
- return ret;
- }
- rawstr = m_xlate(string);
- (void) ctrl_strcpy(ascii, rawstr, TRUE);
- }
- /* if a binding was given on the command line */
- if (argv && *argv && !map)
- if (is_bind_macro)
- (void) strcpy(buf, "macro");
- else
- (void) strcpy(buf, *argv++);
- else {
- /* at this point, "rawstr" and "ascii" should both be set */
- int binding;
-
- if (!strcmp(ascii, "-?")) {
- if (iscurses)
- clr_bot_line();
- ret -= help(0, name, cmd_help);
- if (iscurses)
- off_intr();
- /* Subtract iscurses to signal CNTD_CMD */
- return ret - iscurses;
- }
-
- if (!map && !is_bind_macro) {
- binding = c_bind(rawstr, *map_list);
-
- for (len = 0; len == 0; ) {
- print("\"%s\" = <%s>: New binding [<CR> for list]: ",
- ascii, (binding? map_func_names[binding].m_str : "unset"));
- len = Getstr(buf, sizeof buf, 0);
- if (iscurses)
- clr_bot_line();
- /* strip any trailing whitespace */
- if (len > 0)
- len = no_newln(buf) - buf;
- if (len == 0) {
- (void) do_pager(NULL, TRUE);
- if (iscurses)
- putchar('\n');
- for (x = 1; x <= C_HELP; x++) {
- if (!(x % 4))
- if (do_pager("\n", FALSE) == EOF)
- break;
- (void) do_pager(sprintf(buf, "%-15.15s ",
- map_func_names[x].m_str), FALSE);
- }
- (void) do_pager("\n", FALSE);
- (void) do_pager(NULL, FALSE);
- ret -= iscurses;
- }
- }
- } else /* map */
- (void) strcpy(buf, "macro"), len = 5;
- /* if list was printed, ret < -1 -- tells CNTD_CMD to be set and
- * prevents screen from being refreshed (lets user read output
- */
- if (len == -1) {
- if (iscurses)
- off_intr();
- return ret;
- }
- }
- for (x = 1; x <= C_HELP; x++) {
- if (prefix(buf, map_func_names[x].m_str) == MATCH) {
- int add_to_ret;
- if (debug)
- print("\"%s\" will execute \"%s\".\n", ascii, buf);
- if (map_func_names[x].m_cmd == C_MACRO) {
- if (argv && *argv) {
- (void) argv_to_string(buf, argv);
- (void) m_xlate(buf); /* Convert buf to raw chars */
- add_to_ret =
- do_bind(rawstr, map_func_names[x].m_cmd, buf, map_list);
- } else {
- char exp[MAX_MACRO_LEN*2]; /* printable expansion */
- char *mapping = c_macro(NULL, rawstr, *map_list);
-
- if (mapping)
- (void) ctrl_strcpy(exp, mapping, TRUE);
- print("\"%s\" = <%s>", ascii, mapping ? exp : "unset");
- putchar('\n'), print("New macro: ");
- ret -= iscurses; /* To signal screen messed up */
- /* we are done with buf, so we can trash over it */
- len = Getstr(buf, MAX_MACRO_LEN, 0);
- if (len > 0) {
- if (iscurses)
- clr_bot_line();
- (void) m_xlate(buf); /* Convert buf to raw chars */
- add_to_ret =
- do_bind(rawstr, C_MACRO, buf, map_list);
- if (debug) {
- (void) ctrl_strcpy(exp, buf, TRUE);
- print("\"%s\" will execute \"%s\".\n", ascii, exp);
- }
- } else if (len < 0) {
- if (iscurses)
- off_intr();
- return ret;
- } else
- print("Can't bind to null macro"), putchar('\n');
- }
- } else /* not a macro */ {
- (void) argv_to_string(buf, argv);
- add_to_ret =
- do_bind(rawstr, map_func_names[x].m_cmd, buf, map_list);
- }
- /* if do_bind had no errors, it returned -1. If we already
- * messed up the screen, then ret is less than -1. return the
- * lesser of the two to make sure that CNTD_CMD gets set right
- */
- if (iscurses)
- off_intr();
- return min(add_to_ret, ret);
- }
- }
- print("\"%s\": Unknown function.\n", buf);
- if (iscurses)
- off_intr();
- return ret;
- }
-
- /*
- * print current key to command bindings if "str" is NULL.
- * else return the integer "m_cmd" which the str is bound to.
- */
- c_bind(str, opts)
- register char *str;
- register struct cmd_map *opts;
- {
- register int incurses = iscurses;
-
- if (!str) {
- if (!opts) {
- print("No command bindings.\n");
- return C_ERROR;
- }
- if (incurses)
- clr_bot_line(), iscurses = FALSE;
- (void) do_pager(NULL, TRUE);
- (void) do_pager("Current key to command bindings:\n", FALSE);
- (void) do_pager("\n", FALSE);
- }
-
- for (; opts; opts = opts->m_next) {
- char buf[BUFSIZ], buf2[MAX_BIND_LEN], exp[MAX_MACRO_LEN*2], *xp;
- if (!str) {
- (void) ctrl_strcpy(buf2, opts->m_str, FALSE);
- if ((xp = opts->x_str) && opts->m_cmd == C_MACRO)
- xp = ctrl_strcpy(exp, opts->x_str, TRUE);
- if (do_pager(sprintf(buf, "%s\t%-15.15s %s\n",
- buf2, map_func_names[opts->m_cmd].m_str,
- xp? xp : ""),
- FALSE) == EOF)
- break;
- } else
- if (strcmp(str, opts->m_str))
- continue;
- else
- return opts->m_cmd;
- }
-
- iscurses = incurses;
- if (!str)
- (void) do_pager(NULL, FALSE);
- return C_NULL;
- }
-
- /*
- * Doesn't touch messages, but changes macros: return -1.
- * Error output causes return < -1.
- * args is currently the execute string of a macro mapping, but may be
- * used in the future as an argument string for any curses command.
- */
- do_bind(str, func, args, map_list)
- register char *str, *args;
- struct cmd_map **map_list;
- long func;
- {
- register int ret = -1;
- register struct cmd_map *list;
- int match;
-
- if (func == C_MACRO && !check_mac_bindings(args))
- --ret;
- (void) un_bind(str, map_list);
- for (list = *map_list; list; list = list->m_next)
- if ((match = prefix(str, list->m_str)) != NO_MATCH) {
- ret--;
- switch (match) {
- case MATCH:
- puts("Something impossible just happened.");
- when A_PREFIX_B:
- wprint("Warning: \"%s\" prefixes \"%s\" (%s)\n", str,
- list->m_str, map_func_names[list->m_cmd].m_str);
- when B_PREFIX_A:
- wprint("Warning: \"%s\" (%s) prefixes: \"%s\"\n",
- list->m_str, map_func_names[list->m_cmd].m_str, str);
- }
- }
- add_bind(str, func, args, map_list);
- /* errors decrement ret. If ret returns less than -1, CNTD_CMD is set
- * and no redrawing is done so user can see the warning signs
- */
- return ret;
- }
-
- /*
- * add a binding to a list. This may include "map"s or other mappings since
- * the map_list argument can control that. The "func" is an int defined in
- * bindings.h ... the "str" passed is the string the user would have to type
- * to get the macro/map/binding expanded. This must in in raw format: no
- * \n's to mean \015. Convert first using m_xlate().
- */
- add_bind(str, func, args, map_list)
- register char *str, *args;
- struct cmd_map **map_list;
- long func;
- {
- register struct cmd_map *tmp;
-
- if (!str || !*str)
- return;
-
- /* now make a new option struct and set fields */
- if (!(tmp = (struct cmd_map *)calloc((unsigned)1,sizeof(struct cmd_map)))) {
- error("calloc");
- return;
- }
- tmp->m_next = *map_list;
- *map_list = tmp;
-
- tmp->m_str = savestr(str);
- tmp->m_cmd = func; /* strdup handles the NULL case */
- if (args && *args)
- tmp->x_str = savestr(args);
- else
- tmp->x_str = NULL;
- }
-
- static
- un_bind(p, map_list)
- register char *p;
- struct cmd_map **map_list;
- {
- register struct cmd_map *list = *map_list, *tmp;
-
- if (!list || !*list->m_str || !p || !*p)
- return 0;
-
- if (!strcmp(p, (*map_list)->m_str)) {
- *map_list = (*map_list)->m_next;
- xfree (list->m_str);
- if (list->x_str)
- xfree (list->x_str);
- xfree((char *)list);
- return 1;
- }
- for ( ; list->m_next; list = list->m_next)
- if (!strcmp(p, list->m_next->m_str)) {
- tmp = list->m_next;
- list->m_next = list->m_next->m_next;
- xfree (tmp->m_str);
- if (tmp->x_str)
- xfree (tmp->x_str);
- xfree ((char *)tmp);
- return 1;
- }
- return 0;
- }
-
- prefix(a, b)
- register char *a, *b;
- {
- if (!a || !b)
- return NO_MATCH;
-
- while (*a && *b && *a == *b)
- a++, b++;
- if (!*a && !*b)
- return MATCH;
- if (!*a && *b)
- return A_PREFIX_B;
- if (*a && !*b)
- return B_PREFIX_A;
- return NO_MATCH;
- }
-